package com.dykj.fireFighting.common.core.utils;

import org.apache.commons.lang3.RandomUtils;
import org.apache.tomcat.jni.Local;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.WeekFields;
import java.util.*;
import java.util.stream.Collectors;

public class DateUtil {

	public static final long ONE_DAY_MILLS = 3600000 * 24;
	/**

	 * @param startTime
	 *            开始时间
	 * @param endTime
	 *            截止时间
	 * @param format
	 *            格式化字符串
	 * @return 相差时间字符串
	 * @描述 —— 计算两个时间相差几天几小时几分几秒
	 *
	 *
	 */


	public static String dateDiff(String startTime, String endTime, String format) {
		// 按照传入的格式生成一个simpledateformate对象
		SimpleDateFormat sd = new SimpleDateFormat(format);
		long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
		long nh = 1000 * 60 * 60;// 一小时的毫秒数
		long nm = 1000 * 60;// 一分钟的毫秒数
		long ns = 1000;// 一秒钟的毫秒数
		long diff;
		try {
			// 获得两个时间的毫秒时间差异
			diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();
			long day = diff / nd;// 计算差多少天
			long hour = diff % nd / nh;// 计算差多少小时
			long min = diff % nd % nh / nm;// 计算差多少分钟
			long sec = diff % nd % nh % nm / ns;// 计算差多少秒
			return day + "天" + hour + "时" + min + "分" + sec + "秒";
		} catch (ParseException e) {
			return null;
		}
	}

	/*
	 * 将时间转换为时间戳
	 */
	public static String dateToStamp(String s) throws ParseException {
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = simpleDateFormat.parse(s);
		long ts = date.getTime();
		res = String.valueOf(ts);
		return res;
	}

	/*
	 * 将时间戳转换为时间
	 */
	public static String stampToDate(String s) {
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		long lt = new Long(s);
		Date date = new Date(lt);
		res = simpleDateFormat.format(date);
		return res;
	}

	/**
	 *
	 * @param NEWDATE
	 * @param WILLDATE
	 * @return
	 */
	public static int compare_date(String NEWDATE, String WILLDATE) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date dt1 = df.parse(NEWDATE);
            Date dt2 = df.parse(WILLDATE);
            if (dt1.getTime() > dt2.getTime()) {
                return 1;
            } else if (dt1.getTime() < dt2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return 0;
    }

	public static String getNowTimeStr() {
		Date nowTime=new Date();
		SimpleDateFormat time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return time.format(nowTime);
	}
	public static String getNowDateStr() {
		Date nowTime=new Date();
		SimpleDateFormat time=new SimpleDateFormat("yyyy-MM-dd");
		return time.format(nowTime);
	}
	public static Date getNowTime(){
		Date nowTime=new Date();
		SimpleDateFormat time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			return time.parse(time.format(nowTime));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	 private static int getDaysBetween(Date startDate, Date endDate) {
	        return (int) ((endDate.getTime() - startDate.getTime()) / ONE_DAY_MILLS);
	    }

	    /**
	     * 计算两个日期之间的天数差
	     * @param startDate
	     * @param endDate
	     * @return
	     */
	    public static int getDaysGapOfDates(Date startDate, Date endDate) {
	        int date = 0;
	        if (startDate != null && endDate != null) {
	            date = getDaysBetween(startDate, endDate);
	        }
	        return date;
	    }



	/**
	 * 判断两个时间段是否有交集
	 * @param leftStartDate
	 * @param leftEndDate
	 * @param rightStartDate
	 * @param rightEndDate
	 * @return
	 */
	public static boolean isOverlap(Date leftStartDate, Date leftEndDate,Date rightStartDate, Date rightEndDate) {


		return
				((leftStartDate.getTime() >= rightStartDate.getTime())
						&& leftStartDate.getTime() < rightEndDate.getTime())
						||
						((leftStartDate.getTime() > rightStartDate.getTime())
								&& leftStartDate.getTime() <= rightEndDate.getTime())
						||
						((rightStartDate.getTime() >= leftStartDate.getTime())
								&& rightStartDate.getTime() < leftEndDate.getTime())
						||
						((rightStartDate.getTime() > leftStartDate.getTime())
								&& rightStartDate.getTime() <= leftEndDate.getTime());

	}


	/**
	 * 获取当前日期，格式为：yyyy-MM-dd
	 * @return
	 */
    public static String getToday() {
		Date nowTime = new Date();
		SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd");
		return time.format(nowTime);
    }

	/**
	 * 获取当前时间（年月日）
	 * @return date
	 */
	public static String getDate() {
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String dateStr = sdf.format(date);
		return dateStr;
	}


	/**
	 * 取范围日期的随机日期时间,不含边界
	 * @param startDay
	 * @param endDay
	 * @return
	 */
	public  static LocalDateTime randomLocalDateTime(int startDay,int endDay){

		int plusMinus = 1;
		if(startDay < 0 && endDay > 0){
			plusMinus = Math.random()>0.5?1:-1;
			if(plusMinus>0){
				startDay = 0;
			}else{
				endDay = Math.abs(startDay);
				startDay = 0;
			}
		}else if(startDay < 0 && endDay < 0){
			plusMinus = -1;

			//两个数交换
			startDay = startDay + endDay;
			endDay  = startDay - endDay;
			startDay = startDay -endDay;

			//取绝对值
			startDay = Math.abs(startDay);
			endDay = Math.abs(endDay);

		}

		LocalDate day = LocalDate.now().plusDays(plusMinus * RandomUtils.nextInt(startDay,endDay));
		int hour = RandomUtils.nextInt(1,24);
		int minute = RandomUtils.nextInt(0,60);
		int second = RandomUtils.nextInt(0,60);
		LocalTime time = LocalTime.of(hour, minute, second);
		return LocalDateTime.of(day, time);
	}

	/**
	 * 取范围日期的随机日期时间,不含边界
	 * @param startDay
	 * @param endDay
	 * @return
	 */
	public static Date randomDateTime(int startDay,int endDay){
		LocalDateTime ldt = randomLocalDateTime(startDay,endDay);
		ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
		return Date.from(zdt.toInstant());
	}

	/**
	 * 给指定日期+ N 天
	 * @param cur
	 * @param day
	 * @return
	 */
	public static Date getNewDate(Date cur,int day) {
		Calendar c = Calendar.getInstance();
		c.setTime(cur);   //设置时间
		c.add(Calendar.DATE, day); //日期分钟加1,Calendar.DATE(天),Calendar.HOUR(小时)
		Date date = c.getTime(); //结果
		return date;
	}

	/**
	 * 获取当前年的第一天
	 * @return
	 */
	public static String getCurrYearFirst(){
		Calendar currCal=Calendar.getInstance();
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR,currCal.get(Calendar.YEAR));
		Date time = calendar.getTime();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return format.format(time);
	}

	/**
	 * 获取当前年的第一天
	 * @return
	 */
	public static String getCurrYearFirst1(){
		Calendar currCal=Calendar.getInstance();
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR,currCal.get(Calendar.YEAR));
		Date time = calendar.getTime();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		return format.format(time);
	}

	/**
	 * 获取当前年的最后一天
	 * @return
	 */
	public static String getCurrYearLast(){
		Calendar currCal= Calendar.getInstance();
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR,currCal.get(Calendar.YEAR));
		calendar.roll(Calendar.DAY_OF_YEAR,-1);
		Date time = calendar.getTime();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return format.format(time);
	}
	private static List<Date> getBetweenDates(Date start,Date end){
	   List<Date> result = new ArrayList<Date>();
	   Calendar tempStart = Calendar.getInstance();
	   tempStart.setTime(start);
	   tempStart.add(Calendar.DAY_OF_YEAR, 1);

	   Calendar tempEnd = Calendar.getInstance();
	   tempEnd.setTime(end);
	   while (tempStart.before(tempEnd)) {
		 result.add(tempStart.getTime());
		 tempStart.add(Calendar.DAY_OF_YEAR, 1);
	   }
	   return result;
	}
	/**
	 * LocalDate转Date
	 * @param localDate
	 * @return
	 */
	public static Date localDate2Date(LocalDate localDate) {
		if (null == localDate) {
			return null;
		}
		ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
		return Date.from(zonedDateTime.toInstant());
	}

	/**
	 * Date转LocalDate
	 * @param date
	 */
	public static LocalDate date2LocalDate(Date date) {
		if(null == date) {
			return null;
		}
		return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
	}
	public static List<Date> getBetweenDatesAll(Date start,Date end) throws ParseException {
		List<Date> result = new ArrayList<Date>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cal = Calendar.getInstance();
		cal.setTime(start);

		for (long d = cal.getTimeInMillis(); d <= end.getTime(); d = get_D_Plaus_1(cal)) {
			result.add(sdf.parse(sdf.format(d)));
		}
		return result;
	}
	public static long get_D_Plaus_1(Calendar c) {
		c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + 1);
		return c.getTimeInMillis();
	}

	/**
	 * 根据日期获得所在周的日期
	 * @param mdate
	 * @return
	 */
	public static List<String> dateToWeek(Date mdate) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		int b = mdate.getDay();
		Date fdate;
		List<String> list = new ArrayList<String>();
		Long fTime = mdate.getTime() - b * 24 * 3600000;
		for (int a = 1; a <= 7; a++) {
			fdate = new Date();
			fdate.setTime(fTime + (a * 24 * 3600000));
			list.add(a-1, sdf.format(fdate));
		}
		return list;
	}

	/**
	 * 根据指定日期获取上一周日期
	 */
	public static Map<String, String> getLastTime(String dateStr) {
		Map<String, String> map = new HashMap<>(8);
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Date date = sdf.parse(dateStr);
			Calendar calendar1 = Calendar.getInstance();
			Calendar calendar2 = Calendar.getInstance();
			calendar1.setTime(date);
			calendar2.setTime(date);
			int dayOfWeek = calendar1.get(Calendar.DAY_OF_WEEK) - 1;
			if (dayOfWeek <= 0) {
				dayOfWeek = 7;
			}
			int offset1 = 1 - dayOfWeek;
			int offset2 = 7 - dayOfWeek;
			calendar1.add(Calendar.DATE, offset1 - 7);
			calendar2.add(Calendar.DATE, offset2 - 7);
			// 上周一
			String lastBeginDate = sdf.format(calendar1.getTime());
			// 上周日
			String lastEndDate = sdf.format(calendar2.getTime());

			map.put("lastBeginDate", lastBeginDate);
			map.put("lastEndDate", lastEndDate);
		}catch (ParseException e) {
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 获取年中周数
	 * @return
	 */
	public static int getWeekNum() {
		LocalDate today = LocalDate.now();
		WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 4);
		return today.get(weekFields.weekOfWeekBasedYear());
	}

	public static int getYearNum() {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		return calendar.get(Calendar.YEAR);
	}

	/**
	 * 获取星期
	 */
	public static int getWeekDay() {
		Calendar calendar = Calendar.getInstance();
		return calendar.get(Calendar.DAY_OF_WEEK);
	}

    /**
     * 获取当前年份和周
     * @return
     */
    public static String getYearWeek(){
        LocalDate today = LocalDate.now();
        WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 4);
        int year = today.get(weekFields.weekBasedYear());
        int weekOfYear = today.get(weekFields.weekOfWeekBasedYear());
        if(weekOfYear<10){
			return year + "0" + weekOfYear;
		}else{
			return String.valueOf(year) + String.valueOf(weekOfYear);
		}

    }
	/**
	 * 给定开始时间计算第几周
	 */
	public static String getWeek(String startDate){

		SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
		Date start=null;
		try {
			start = format.parse(startDate);
		}catch (Exception e){
			e.printStackTrace();
		}
		Instant instant = start.toInstant();
		ZoneId zoneId = ZoneId.systemDefault();
		LocalDate localDate = instant.atZone(zoneId).toLocalDate();
		WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 4);
		int year = localDate.get(weekFields.weekBasedYear());
		int weekOfYear = localDate.get(weekFields.weekOfWeekBasedYear());
		if(weekOfYear < 10){
			return year + "0" + weekOfYear;
		}
		return String.valueOf(year) + String.valueOf(weekOfYear);
	}


	/**
	 * 获取当前月第一天
	 * @return
	 */
	public static String getMonthFirstDay(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.DAY_OF_MONTH,1);
		calendar.add(Calendar.MONTH,0);
		Date date = calendar.getTime();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		String format = sdf.format(date);
		return format;
	}

	/**
	 * 获取当前月最后一天
	 * @return
	 */
	public static String  getMonthLastDay(){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.set(Calendar.DAY_OF_MONTH,0);
		calendar.add(Calendar.MONTH,1);
		Date time = calendar.getTime();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		String format = sdf.format(time);
		return format;
	}

	/**
	 * 根据一段时间获取该段时间的所有日期  正序排序
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static List<String> getDaysBetweenDate(String startDate, String endDate) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		List<String> dateList = new ArrayList<String>();
		try {
			Date dateOne = sdf.parse(startDate);
			Date dateTwo = sdf.parse(endDate);
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(dateOne);
			dateList.add(startDate);
			while (dateTwo.after(calendar.getTime())) {
				calendar.add(Calendar.DAY_OF_MONTH, 1);
				dateList.add(sdf.format(calendar.getTime()));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return dateList;
	}


	/**
	 * 获取两个日期之间的所有月份 (年月)
	 *
	 * @return：YYYY-MM
	 */
	public static List<String> getMonthBetweenDate(String startTime,String endTime){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		// 声明保存日期集合
		List<String> list = new ArrayList<String>();
		try {
			// 转化成日期类型
			Date startDate = sdf.parse(startTime);
			Date endDate = sdf.parse(endTime);

			//用Calendar 进行日期比较判断
			Calendar calendar = Calendar.getInstance();
			while (startDate.getTime()<=endDate.getTime()){
				// 把日期添加到集合
				list.add(sdf.format(startDate));
				// 设置日期
				calendar.setTime(startDate);
				//把日期增加一天
				calendar.add(Calendar.MONTH, 1);
				// 获取增加后的日期
				startDate=calendar.getTime();
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return list;
	}


	/**
	 *根据时间范围获得季度集
	 * @return
	 */
	public static List<String> getQuarterBetweenDate(String beginDate, String endDate){
		List<String> rangeSet =null;
		SimpleDateFormat sdf = null;
		Date begin_date = null;
		Date end_date = null;
		String[] numStr =null;
		String Q=null;
		rangeSet = new java.util.ArrayList<String>();
		sdf = new SimpleDateFormat("yyyy-MM");
		try {
			//定义起始日期
			begin_date = sdf.parse(beginDate);
			//定义结束日期
			end_date = sdf.parse(endDate);
		} catch (ParseException e) {
			System.out.println("时间转化异常，请检查你的时间格式是否为yyyy-MM或yyyy-MM-dd");
		}
		//定义日期实例
		Calendar dd = Calendar.getInstance();
		//设置日期起始时间
		dd.setTime(begin_date);
		//判断是否到结束日期
		while(!dd.getTime().after(end_date)){
			numStr=  sdf.format(dd.getTime()).split("-",0);
			Q = getQuarter(Integer.valueOf(numStr[1]))+"";
			// System.out.println(numStr[0].toString()+"年第"+Q+"季");
			rangeSet.add(numStr[0].toString()+"-"+Q);
			//进行当前日期月份加1
			dd.add(Calendar.MONTH, 1);
		}
		//去重返回
		return rangeSet.stream().distinct().collect(Collectors.toList());
	}

	/**
	 * 根据月获得季度
	 * @param month  月
	 * @return  季度
	 */
	private static int getQuarter(int month) {
		if(month == 1 || month == 2 || month == 3){
			return 1;
		}else if(month == 4 || month == 5 || month == 6){
			return  2;
		}else if(month == 7 || month == 8 || month == 9){
			return 3;
		}else{
			return 4;
		}
	}

	/**
	 *根据时间范围获得年份集
	 * @return
	 */
	public static List<String> getYearBetweenDate(String startTime, String endTime) {
		List<String> result = new ArrayList<>();
		SimpleDateFormat sdf;
		Calendar start = Calendar.getInstance();
		Calendar end = Calendar.getInstance();
		try {
			sdf = new SimpleDateFormat("yyyy");
			start.setTime(sdf.parse(startTime));
			end.setTime(sdf.parse(endTime));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		Calendar curr = start;
		sdf = new SimpleDateFormat("yyyy");
		while (curr.before(end)) {
			result.add(sdf.format(curr.getTime()));
			curr.add(Calendar.YEAR, 1);
		}
		result.add(sdf.format(end.getTime()));
		return result.stream().distinct().collect(Collectors.toList());
	}



	public static void main(String[] args) throws ParseException {
		List<String> quarterBetweenDate = getYearBetweenDate("2019-03-31", "2022-04-26");
		System.out.println(quarterBetweenDate);
	}

	public static Date asDate(LocalDate localDate) {
		return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
	}

	public static Date asDate(LocalDateTime localDateTime) {
		return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
	}

	public static LocalDate asLocalDate(Date date) {
		return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
	}

	public static LocalDateTime asLocalDateTime(Date date) {
		return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
	}

	/**
	 * 获取半年前的日期
	 * @param startDate
	 * @return
	 */

	public static String getBeforeHalfYearDateStr(Date startDate)throws Exception
	{
		Calendar calendar=Calendar.getInstance();
		SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
		calendar.setTime(startDate);
		calendar.add(Calendar.MONTH,-6);
		Date newDate=calendar.getTime();
		return simpleDateFormat.format(newDate);

	}




}
